
#ifndef __TF_CONFIGURATOR_H__
#define __TF_CONFIGURATOR_H__

#include <string>
#include <map>
#include <list>
#include <sstream>
#include <cstdlib>
#include <algorithm>
using namespace std;


#ifndef __TF_DEBUG__
#define __TF_DEBUG__
#endif


class TFConfigurator
{
public:
    TFConfigurator(const char *,const char*,bool readonly=false);
    TFConfigurator(TFConfigurator&){}
    ~TFConfigurator();

    //Getter;
    bool ReadOnly()
    {
        return readonly;
    }
    bool Modified()
    {
        return modified;
    }

    //Get config value;
    template<typename ValueType>
        ValueType GetConfigValue(string &key)
    {
        ValueType ret(key);
        return ret;
    }
    template<>
        string GetConfigValue(string& key)
    {
        ConfigMap::iterator itr=configs.find(key);
        if(itr!=configs.end())
        {
            return itr->second;
        }
        string ret;
        return ret;
    }
    template<>
        int GetConfigValue(string &key)
    {
        string value=GetConfigValue<string>(key);
        return atoi(value.c_str());
    }
    template<>
        double GetConfigValue(string &key)
    {
        string value=GetConfigValue<string>(key);
        return atof(value.c_str());
    }
    
    //Set config value, generic template function;
    template <typename ValueType>
        bool SetConfigValue(string &key, ValueType &dat)
    {
        if(readonly)
            return false;
        ostringstream oss;
        oss.clear();
        oss<<dat;
        return SetConfigValue(key,oss.str());
    }

    //Specialize for std::string type;
    template<>
        bool SetConfigValue(string &key, string &value)
    {
        if(readonly)
            return false;
        
        ConfigMap::iterator itr=configs.find(key);
        //Modify the action records to be comfort the write back operation;
        if(itr!=configs.end())
        {
            if(itr->second!=value){
                itr->second=value;
                //This is a new inserted config,and modified again before write back
                if( find<list<ConfigMap::iterator>::iterator,ConfigMap::iterator>(
                        new_configs.begin(),
                        new_configs.end(),
                        itr)
                    != new_configs.end()
                    )
                {
                    modified_configs.push_back(itr);
                    new_configs.remove(itr);
                }
                if(find<list<ConfigMap::iterator>::iterator,ConfigMap::iterator>(
                       modified_configs.begin(),
                       modified_configs.end(),
                       itr)
                   ==modified_configs.end())
                {
                    modified_configs.push_back(itr);
                }
            }
        }else{
            ConfigMap::iterator itr=(configs.insert(pair<string,string>(key,value))).first;
            new_configs.push_back(itr);
        }
        modified=true;
        return true;
    }

    void WriteBack();

#ifdef __TF_DEBUG__
    void ShowAll();
#endif

public:
    typedef map<string,string> ConfigMap;
    typedef list<ConfigMap::iterator> ConfigMapIteratorList;
protected:
    bool modified;
    bool readonly;
    ConfigMap configs;
    ConfigMapIteratorList new_configs;
    ConfigMapIteratorList modified_configs;
private:
    string config_table;
    string database;
};

#endif //__TF_CONFIGURATOR_H__
